Release 3.6.0 to main - #307
Conversation
Fix the URL correction for doctor update
* fix: amm-1584 * fix: amm-1583 * fix: amm-1589 * fix: code rabitt fixs * fix: amm-1593 * fix: amm-1590 aam-1591 * fix: amm-1592 * fix: removed extra angle bracket * fix: inventory redirection issue fixed * fix: remove the additional slash in the url to fix the 404 issue * fix: amm-1585 css fixes * fix: amm-1583 facilityId was passing encrypted --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com>
* fix: amm-1584 * fix: amm-1583 * fix: amm-1589 * fix: code rabitt fixs * fix: amm-1593 * fix: amm-1590 aam-1591 * fix: amm-1592 * fix: removed extra angle bracket * fix: inventory redirection issue fixed * fix: remove the additional slash in the url to fix the 404 issue * fix: amm-1585 css fixes * fix: amm-1583 facilityId was passing encrypted * fix: amm-1579 --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com>
* fix: remove the additional slash in the url to fix the 404 issue * fix: past obstetric history dropdown changes --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> Co-authored-by: Karyamsetty Helen Grace <ka40094929@wipro.com>
fix: amm-1730 action buttons issue fix in chief complaints
* fix: disply error msg based on the response * Revert "fix: disply error msg based on the response" This reverts commit 6273191. * fix for 1585, 1583 (#189) * fix: amm-1584 * fix: amm-1583 * fix: amm-1589 * fix: code rabitt fixs * fix: amm-1593 * fix: amm-1590 aam-1591 * fix: amm-1592 * fix: removed extra angle bracket * fix: inventory redirection issue fixed * fix: remove the additional slash in the url to fix the 404 issue * fix: amm-1585 css fixes * fix: amm-1583 facilityId was passing encrypted --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> * Amm-1579 (#192) * fix: amm-1584 * fix: amm-1583 * fix: amm-1589 * fix: code rabitt fixs * fix: amm-1593 * fix: amm-1590 aam-1591 * fix: amm-1592 * fix: removed extra angle bracket * fix: inventory redirection issue fixed * fix: remove the additional slash in the url to fix the 404 issue * fix: amm-1585 css fixes * fix: amm-1583 facilityId was passing encrypted * fix: amm-1579 --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> * fix: amm-1580 * fix: amm-1597 * fix: amm-1583 * fix: amm-1655 * Update version in pom.xml to 3.4.0 * Update pom.xml * Update pom.xml * Update pom.xml * fix: show the message on token expiry (#200) * fix: amm-1416 (#199) * fix: refer resaon should disable initial (#203) * AMM-1577 & AMM-1578 Menstrual History & Obstetric History changes (#204) * fix: remove the additional slash in the url to fix the 404 issue * fix: past obstetric history dropdown changes --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> Co-authored-by: Karyamsetty Helen Grace <ka40094929@wipro.com> * fix: amm-1747 and amm-1583 (#208) * fix: amm-1730 action buttons issue fix in chief complaints --------- Co-authored-by: SnehaRH <sneha@navadhiti.com> Co-authored-by: Amoghavarsh <93114621+5Amogh@users.noreply.github.com> Co-authored-by: SnehaRH <77656297+snehar-nd@users.noreply.github.com> Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> Co-authored-by: Vishwanath Balkur <118195001+vishwab1@users.noreply.github.com> Co-authored-by: Karyamsetty Helen Grace <ka40094929@wipro.com> Co-authored-by: 5Amogh <amoghavarsh@navadhiti.com>
fix: amm-1668 beneficiary details addition
* fix: remove the additional slash in the url to fix the 404 issue * fix: past obstetric history dropdown changes * Release 3.4.0 (#1) * fix: disply error msg based on the response * Revert "fix: disply error msg based on the response" This reverts commit 6273191. * fix for 1585, 1583 (#189) * fix: amm-1584 * fix: amm-1583 * fix: amm-1589 * fix: code rabitt fixs * fix: amm-1593 * fix: amm-1590 aam-1591 * fix: amm-1592 * fix: removed extra angle bracket * fix: inventory redirection issue fixed * fix: remove the additional slash in the url to fix the 404 issue * fix: amm-1585 css fixes * fix: amm-1583 facilityId was passing encrypted --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> * Amm-1579 (#192) * fix: amm-1584 * fix: amm-1583 * fix: amm-1589 * fix: code rabitt fixs * fix: amm-1593 * fix: amm-1590 aam-1591 * fix: amm-1592 * fix: removed extra angle bracket * fix: inventory redirection issue fixed * fix: remove the additional slash in the url to fix the 404 issue * fix: amm-1585 css fixes * fix: amm-1583 facilityId was passing encrypted * fix: amm-1579 --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> * fix: amm-1580 * fix: amm-1597 * fix: amm-1583 * fix: amm-1655 * Update version in pom.xml to 3.4.0 * Update pom.xml * Update pom.xml * Update pom.xml * fix: show the message on token expiry (#200) * fix: amm-1416 (#199) * fix: refer resaon should disable initial (#203) * AMM-1577 & AMM-1578 Menstrual History & Obstetric History changes (#204) * fix: remove the additional slash in the url to fix the 404 issue * fix: past obstetric history dropdown changes --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> Co-authored-by: Karyamsetty Helen Grace <ka40094929@wipro.com> * fix: amm-1747 and amm-1583 (#208) * fix: amm-1730 action buttons issue fix in chief complaints --------- Co-authored-by: SnehaRH <sneha@navadhiti.com> Co-authored-by: Amoghavarsh <93114621+5Amogh@users.noreply.github.com> Co-authored-by: SnehaRH <77656297+snehar-nd@users.noreply.github.com> Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> Co-authored-by: Vishwanath Balkur <118195001+vishwab1@users.noreply.github.com> Co-authored-by: Karyamsetty Helen Grace <ka40094929@wipro.com> Co-authored-by: 5Amogh <amoghavarsh@navadhiti.com> * fix(bug): ncd-care-diagnosis and provisional diagnosis doctor patch issue --------- Co-authored-by: Vanitha <vanitha@navadhiti.com> Co-authored-by: Vanitha S <116701245+vanitha1822@users.noreply.github.com> Co-authored-by: Karyamsetty Helen Grace <ka40094929@wipro.com> Co-authored-by: SnehaRH <sneha@navadhiti.com> Co-authored-by: Amoghavarsh <93114621+5Amogh@users.noreply.github.com> Co-authored-by: SnehaRH <77656297+snehar-nd@users.noreply.github.com> Co-authored-by: Vishwanath Balkur <118195001+vishwab1@users.noreply.github.com> Co-authored-by: 5Amogh <amoghavarsh@navadhiti.com>
* fix: provisonal diagnosis values patching issue * fix: added confirmatory feild name * fix: file upload issue, file displaying duplicate
📝 WalkthroughWalkthroughThis PR introduces comprehensive user interaction tracking via AmritTrackingService across the application, implements a new SMS prescription notification feature, enhances diagnosis autocomplete with server-side pagination and lazy-loading, updates feedback and login navigation flows, modifies HTTP interceptor for platform-feedback requests, and extends environment configurations with tracking and SMS endpoints. Changes
Sequence DiagramssequenceDiagram
participant User
participant Dialog as SMS Dialog
participant Service as SmsTemplateService
participant Backend
User->>Dialog: Enters mobile number
Dialog->>Service: Fetch SMS Types
Service->>Backend: POST getSMStypes
Backend-->>Service: SMS types list
Service-->>Dialog: SMS types populated
Dialog->>Service: Fetch SMS Templates
Service->>Backend: POST getSMStemplates
Backend-->>Service: Templates list
Service-->>Dialog: Templates populated
User->>Dialog: Click "Send SMS"
Dialog->>Service: sendSMS(payload array)
Service->>Backend: POST sendSMS
Backend-->>Service: Success response
Service-->>Dialog: Show success snackbar
Dialog->>Dialog: Close dialog
sequenceDiagram
participant User
participant Input as Diagnosis Input
participant Directive as AutocompleteScroller
participant Component
participant Service as MasterdataService
User->>Input: Type diagnosis (3+ chars)
Input->>Component: onDiagnosisInputKeyup
Component->>Component: Initialize pagination state
Component->>Component: fetchPage(index, false)
Component->>Service: Query diagnosis data
Service-->>Component: Initial results batch
Component->>Component: suggestedDiagnosisList[i] = results
Component-->>Input: Display options
Directive->>Component: onPanelReady (panel opened)
Component->>Component: bootstrapUntilScrollable
loop Until scrollable or max pages
Component->>Service: Fetch next page
Service-->>Component: More results
Component->>Component: Append & deduplicate
end
User->>Directive: Scroll near end (threshold 0.6)
Directive->>Component: onAutoNearEnd
Component->>Component: fetchPage(index, true)
Component->>Service: Fetch append page
Service-->>Component: Additional results
Component->>Component: Merge with existing
Component-->>Input: Update display
sequenceDiagram
participant User
participant AppHeader
participant Router
participant Feedback as FeedbackModule
User->>AppHeader: Click logout
AppHeader->>Router: navigate([/feedback], { queryParams: { sl: 'MMU' } })
Router->>Feedback: Load feedback module lazily
Feedback-->>Router: Module loaded
Router-->>User: Display feedback component
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom Pre-merge Checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
There was a problem hiding this comment.
Actionable comments posted: 15
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (9)
src/app/app-modules/nurse-doctor/case-sheet/general-case-sheet/doctor-diagnosis-case-sheet/doctor-diagnosis-case-sheet.component.html (1)
1442-1451: Guard the Doctor's Sign section with a conditional to match the signature availability logic.The section wrapper (line 1442) renders unconditionally, meaning the "Doctor's Sign:" label always displays even when no signature is available. The
imgUrlis only populated whencaseSheetData?.BeneficiaryData?.doctorSignatureFlagis true (lines 432-434), but this condition doesn't prevent the label from rendering.Add a conditional guard to the wrapper:
<div class="row m-t-50" *ngIf="imgUrl"> <div class="col-xs-6"> </div> <div class="col-xs-6"> <p> <strong> {{ currentLanguageSet?.casesheet?.docSign }}:</strong> <img [src]="imgUrl" alt="sign" *ngIf="imgUrl" /> </p> </div> </div>This prevents the entire section from displaying when there's no signature, avoiding the confusing orphaned label.
scripts/ci-prebuild.js (2)
28-28: Addejsto dependencies in package.json.The script requires the
ejsmodule but it's not declared inpackage.json. This will cause the script to fail in CI environments where dependencies aren't pre-installed.
25-28: Addejsto package.json dependencies.The
ejsmodule is required in line 28 of this script but is not declared inpackage.json. Add it to the dependencies section to ensure proper package management and reproducibility:"dependencies": { ... "ejs": "^3.1.7" }src/app/app-modules/nurse-doctor/shared/services/doctor.service.ts (1)
952-1016: Add missingdoctorSignatureFlagparameter topostDoctorCovidCareDetailsmethod.All other
postDoctor*Detailsmethods in this service include thedoctorSignatureFlagparameter and add it to their payloads, butpostDoctorCovidCareDetailsomits it. The call site inworkarea.component.tsalso needs to be updated to pass this parameter.Changes required
In
doctor.service.tsmethod signature (lines 952–954):postDoctorCovidCareDetails( patientMedicalForm: any, otherDetails: any, tcRequest: any, + doctorSignatureFlag: any ) {In the payload (before the
returnstatement):createdBy: this.sessionstorage.getItem('userName'), tcRequest: tcRequest, + doctorSignatureFlag: doctorSignatureFlag, };In
workarea.component.tscall site:this.doctorService .postDoctorCovidCareDetails( this.patientMedicalForm, temp, - this.schedulerData + this.schedulerData, + this.doctorSignatureFlag )src/app/app-modules/nurse-doctor/workarea/workarea.component.ts (1)
1073-1088: Critical: Double navigation when SMS is sent for Cancer Screening.When
prescribedDrugs.length > 0, bothsendPrescriptionSms()(which navigates after dialog closes at lines 2511-2516) and the explicitrouter.navigateat lines 1084-1088 are executed. This causes immediate navigation followed by another navigation attempt when the dialog closes, leading to unpredictable behavior.Other visit types correctly use an
elsebranch to avoid this issue.🔎 Proposed fix
if (res.statusCode === 200 && res.data !== null) { this.patientMedicalForm.reset(); - this.confirmationService.alert(res.data.response, 'success'); if (prescribedDrugs.length > 0) { const prescriptionSmsObject = this.SMSObjectCreation( [], prescribedDrugs, res.data.prescribedDrugIDs ); this.sendPrescriptionSms(prescriptionSmsObject); - } - if (this.isSpecialist) { - this.router.navigate(['/common/tcspecialist-worklist']); } else { - this.router.navigate(['/nurse-doctor/doctor-worklist']); + this.confirmationService.alert(res.data.response, 'success'); + if (this.isSpecialist) { + this.router.navigate(['/common/tcspecialist-worklist']); + } else { + this.router.navigate(['/nurse-doctor/doctor-worklist']); + } } }src/app/app-modules/service-point/service-point.component.html (1)
16-28:(selectionChange)event does not exist onmat-radio-group.Angular Material's
mat-radio-groupemits a(change)event, not(selectionChange). The tracking call on line 19 will never fire. You should move the tracking call into the(change)handler or rename the event.🔎 Proposed fix
<mat-radio-group formControlName="sessionID" - (change)="filterVansList()" - (selectionChange)="trackFieldInteraction('Service Type')"> + (change)="filterVansList(); trackFieldInteraction('Service Type')">src/app/app-modules/nurse-doctor/nurse-doctor.module.ts (1)
169-169: Remove duplicate MatChipsModule import.
MatChipsModuleappears twice in the imports array (lines 169 and 173). Remove the duplicate entry.🔎 Proposed fix
MatTableModule, - MatChipsModule, MatDatepickerModule, NgxPaginationModule, SharedModule, MatChipsModule, MatToolbarModule,Also applies to: 173-173
src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/ncd-screening-diagnosis/ncd-screening-diagnosis.component.ts (1)
87-93: Potential memory leak: Subscription not unsubscribed.The subscription to
nurseService.enableProvisionalDiag$is not stored or unsubscribed inngOnDestroy. This can cause memory leaks if the component is destroyed while the observable is still active.Proposed fix
+ import { Subscription } from 'rxjs'; ... diagnosisSubscription: any; + private enableProvisionalDiagSub!: Subscription; ... ngOnInit() { console.log('caseRecordMode', this.caseRecordMode); console.log('doctorDiagnosis', this.doctorDiagnosis); - this.nurseService.enableProvisionalDiag$.subscribe(response => { + this.enableProvisionalDiagSub = this.nurseService.enableProvisionalDiag$.subscribe(response => { if (response) { this.enableProvisionalDiag = true; } else { this.enableProvisionalDiag = false; } }); } + + ngOnDestroy() { + this.enableProvisionalDiagSub?.unsubscribe(); + this.diagnosisSubscription?.unsubscribe(); + }src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/ncd-care-diagnosis/ncd-care-diagnosis.component.ts (1)
170-184: Critical bug:addDiagnosis()called inside loop causes incomplete row expansion.The condition
if (diagnosisArrayList.length < savedDiagnosisData.length)is checked inside the loop after patching each index. This is problematic because:
- On iteration
i=1, ifdiagnosisArrayList.lengthis 1 andsavedDiagnosisData.lengthis 3, it adds only one row- On iteration
i=2,diagnosisArrayList.at(2)may not exist yet, causing the patch to fail or target undefinedThe rows should be expanded before the loop starts (as done correctly in
ncd-screening-diagnosis.component.tsusing awhileloop).Proposed fix
patchProvisionalDiagnosisDetails(provisionalDiagnosis: any) { const savedDiagnosisData = provisionalDiagnosis; const diagnosisArrayList = this.generalDiagnosisForm.controls[ 'provisionalDiagnosisList' ] as FormArray; if ( provisionalDiagnosis[0].term !== '' && provisionalDiagnosis[0].conceptID !== '' ) { + // Expand array to fit all saved diagnoses BEFORE patching + while (diagnosisArrayList.length < savedDiagnosisData.length) { + this.addDiagnosis(); + } for (let i = 0; i < savedDiagnosisData.length; i++) { diagnosisArrayList.at(i).patchValue({ viewProvisionalDiagnosisProvided: savedDiagnosisData[i].term, term: savedDiagnosisData[i].term, conceptID: savedDiagnosisData[i].conceptID, }); (<FormGroup>diagnosisArrayList.at(i)).controls[ 'viewProvisionalDiagnosisProvided' ].disable(); - - if (diagnosisArrayList.length < savedDiagnosisData.length) { - this.addDiagnosis(); - } } } }
🤖 Fix all issues with AI agents
In @src/app/app-modules/core/services/http-service.service.ts:
- Around line 25-28: The constructor in HttpServiceService calls JSON.parse on
localStorage.getItem('appLanguage') without protecting against invalid JSON;
wrap the parse in a try/catch around the retrieval of
localStorage.getItem('appLanguage') inside the constructor, assign this.language
= null on parse failure (or when value is null), and log or remove the corrupted
key (e.g., console.error or localStorage.removeItem('appLanguage')) so service
initialization doesn't throw; reference the constructor,
localStorage.getItem('appLanguage'), JSON.parse, and this.language when making
the change.
In
@src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts:
- Around line 55-56: The code imports and likely uses AmritTrackingService to
track sensitive field-level interactions (ePHI); update FindingsComponent (and
any components using AmritTrackingService) to enforce a centralized
privacy-and-compliance gating layer: require explicit, recorded user consent
before enabling AmritTrackingService for health fields, consult/add a DPIA entry
for this processing, ensure audit events are stored via an encrypted,
access-controlled audit pipeline (encrypt at rest/in transit and use a
BA-approved vendor), apply pseudonymization/minimum-necessary transformations
before sending analytics (aggregate or role-scoped summaries where possible),
include retention and access details in the app privacy notice, and move these
checks into a shared tracking wrapper/service so components call a
consent-and-compliance-checked API rather than using AmritTrackingService
directly.
In
@src/app/app-modules/nurse-doctor/history/general-opd-history/past-history/past-history.component.html:
- Around line 99-100: The analytics tracking labels for duration and time-unit
fields are ambiguous because both Past Illness and Past Surgery use the same
labels; update the calls to trackFieldInteraction in the template (where
validateDuration(pastIllness) and similar handlers are used) to pass distinct
labels prefixed by section (e.g., "PastIllness: Duration", "PastIllness: Time
Period Unit" and analogous "PastSurgery: Duration", "PastSurgery: Time Period
Unit") so analytics can distinguish sections; ensure every occurrence referenced
in the diff (the trackFieldInteraction invocations around validateDuration and
the time unit select) is updated consistently.
In @src/app/app-modules/nurse-doctor/quick-consult/quick-consult.component.html:
- Around line 643-645: The remove-button condition wrongly checks
diagnosis.get('provisionalDiagnosisList')?.disabled (a non-existent child
control); change it to reference the actual top-level FormArray's disabled state
instead (e.g., use the parent form or the provisionalDiagnosisList FormArray:
parentForm.get('provisionalDiagnosisList')?.disabled or
provisionalDiagnosisList?.disabled) while keeping the other checks (i !== 0 ||
...); note that each diagnosis FormGroup only has conceptID, term, and
provisionalDiagnosis, so do not attempt to access provisionalDiagnosisList from
diagnosis.
In
@src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.html:
- Line 48: The paginator is not wired to the table because the template uses
*ngFor over data.prescribedDrugs instead of a MatTableDataSource; replace the
direct *ngFor table with an Angular Material table bound to a MatTableDataSource
(e.g., create a dataSource = new
MatTableDataSource<any>(this.data.prescribedDrugs)), add
@ViewChild(MatPaginator) paginator!: MatPaginator, and in ngAfterViewInit assign
this.dataSource.paginator = this.paginator so the mat-paginator controls paging;
alternatively remove the mat-paginator if pagination is not required.
In
@src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.spec.ts:
- Around line 9-16: TestBed.configureTestingModule for SmsNotificationComponent
is missing required Angular Material modules, Forms/Common modules, and
providers; update the TestBed.configureTestingModule call to include imports:
MatDialogModule, MatToolbarModule, MatIconModule, MatPaginatorModule,
MatCheckboxModule, MatFormFieldModule, MatInputModule, MatButtonModule,
FormsModule, CommonModule, and add providers that supply mock implementations
for SmsTemplateService, ConfirmationService, HttpServiceService,
SessionStorageService plus provide MAT_DIALOG_DATA with a test object containing
a prescribedDrugs array; create simple spy objects or jasmine.createSpyObj for
these services and pass them in the providers array so fixture =
TestBed.createComponent(SmsNotificationComponent) and fixture.detectChanges()
can run without DI or template compilation errors.
In
@src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.ts:
- Line 22: The SmsNotificationComponent declares ngOnInit and ngDoCheck but does
not implement the corresponding interfaces; update the SmsNotificationComponent
class to implement OnInit and DoCheck and add the necessary imports from
@angular/core, ensure the class signature includes "implements OnInit, DoCheck"
and that the ngOnInit() and ngDoCheck() method signatures match the interface
contracts so AOT and style rules are satisfied.
- Around line 148-150: The dialog is being closed synchronously before the async
subscribe callbacks run; move this.dialogRef.close() into the subscribe's next
callback (and optionally into the error callback) so the dialog only closes
after the async SMS send completes and the success or error snackbar is shown;
locate the subscribe call in sms-notification.component (the call that sends SMS
and uses subscribe with next/error) and remove the top-level
this.dialogRef.close(), then invoke this.dialogRef.close() inside the subscribe
next handler (and call it or handle UI appropriately in the error handler).
In @src/app/app-modules/nurse-doctor/smsTemplate/sms-template.service.spec.ts:
- Around line 27-38: The TestBed setup for SmsTemplateService is missing
providers for its dependencies; update TestBed.configureTestingModule to provide
SmsTemplateService plus mocked providers for HttpClient and HttpServiceService
(e.g., supply a jasmine spy object for HttpClient methods used by
SmsTemplateService and a simple stub for HttpServiceService) so that
TestBed.inject(SmsTemplateService) resolves without NullInjectorError.
In
@src/app/app-modules/nurse-doctor/visit-details/visit-details/visit-details.component.html:
- Around line 87-89: The mat-select for pregnancyStatus is using [attr.readonly]
which has no effect; change the binding to use [disabled] so the control is
actually disabled when visitCategory is 'ANC'. Update the pregnancyStatus
<mat-select> to bind [disabled] to the expression
patientVisitDetailsForm.controls['visitCategory'].value === 'ANC' (or the local
visitCategory getter if present) so the field is properly disabled instead of
attempting to set a readonly attribute.
In
@src/app/app-modules/nurse-doctor/vitals/general-patient-vitals/general-patient-vitals.component.html:
- Around line 247-248: The validation in checkNurseRequirements() is too broad:
narrow the waist circumference check so it only runs when visitCategory === 'NCD
screening' AND benAge >= 30 (to match the template's [required]="benAge >= 30 &&
visitCategory === 'NCD screening'"); update the error label reference from
vitalsCancerscreening_QC.waistCircumference to the correct NCD screening field
name used elsewhere (e.g., vitalsNCDscreening_QC.waistCircumference or the
module's NCD-specific label) so the error message aligns with the NCD workflow.
In @src/app/app-modules/nurse-doctor/workarea/workarea.component.ts:
- Around line 3104-3118: The code is using the wrong form reference: replace
uses of this.patientVisitForm when building the provisionalDiagnosisList for SMS
with the patientCaseRecordForm instance (as done in
submitGeneralOPDDiagnosisForm) so you don't call .value on null; specifically,
obtain the FormArray value from the patientCaseRecordForm (the
generalDiagnosisForm.provisionalDiagnosisList) before calling SMSObjectCreation,
then pass that value into SMSObjectCreation and continue to call
sendPrescriptionSms with the resulting prescriptionSmsObject; update references
around SMSObjectCreation and ensure the local variable name matches the pattern
used elsewhere (e.g., patientCaseRecordForm) to avoid null pointer exceptions.
In @src/assets/Assamese.json:
- Around line 1724-1741: Several ABHA-related i18n keys
(enterMobileNumberToBeLinkedWithAbha, doYouWantToVerifyMobileOtpForAbha,
abhaCardAlreadyExists, enterABHANumber, enterABHAAddress, enterAadhaarNumber,
enterMobileNumber, enterCorrectAuthIdForAuthMode, abhaAddressFound,
searchAndDownloadAbha, abhaSearchMode, verifyAbha, issueInAbhaCard,
fileUploadedSuccessfully, verifyMobileOtp, enterMobileOtp, verify,
abhaNumberAlreadyWith) are still in English; replace each English value with the
appropriate Assamese translation so the UI is consistent, or if leaving them in
English is intentional for a staged rollout, add a clear TODO comment next to
each key indicating why and when the Assamese translations will be added. Ensure
you update the exact JSON entries for those keys (matching the key names above)
and keep JSON syntax valid.
In @src/assets/Hindi.json:
- Around line 1727-1745: Several ABHA-related localization entries (e.g.,
enterMobileNumberToBeLinkedWithAbha, doYouWantToVerifyMobileOtpForAbha,
abhaCardAlreadyExists, enterABHANumber, enterABHAAddress, enterAadhaarNumber,
enterMobileNumber, enterCorrectAuthIdForAuthMode, abhaAddressFound,
searchAndDownloadAbha, abhaSearchMode, verifyAbha, issueInAbhaCard,
fileUploadedSuccessfully, verifyMobileOtp, enterMobileOtp, verify,
abhaNumberAlreadyWith, enterTenDigitMobileNumber) currently contain English
values; replace each value with the correct Hindi (Devanagari) translation
matching the file’s existing style (for example
enterMobileNumberToBeLinkedWithAbha -> "ABHA से जोड़ने के लिए फोन नंबर दर्ज
करें", verify -> "सत्यापित करें") ensuring punctuation and capitalization follow
local conventions, and run a quick lint/validation of the JSON to confirm no
syntax changes were introduced.
🟡 Minor comments (14)
src/assets/English.json-14-14 (1)
14-14: Clarify the consent checkbox logic.The text "Submit anonymously (if unchecked, we will store your user id for follow-up)" is confusing. If the checkbox is unchecked, the feedback should NOT be anonymous, so saying "Submit anonymously" when unchecked is contradictory.
Consider rephrasing to make the behavior clear, such as:
- "Submit anonymously" (simpler checkbox label)
- Or: "Do not store my user ID (submit anonymously)"
src/assets/Assamese.json-57-57 (1)
57-57: Remove the trailing 'e' character.The Assamese translation has an English letter 'e' at the end: "মাহিলি পৰিয়াল আয়e". This appears to be a typo.
🔎 Suggested fix
- "monthlyFamilyIncome": "মাহিলি পৰিয়াল আয়e", + "monthlyFamilyIncome": "মাহিলি পৰিয়াল আয়",src/assets/English.json-1757-1757 (1)
1757-1757: Align the display text with the key name.The key name is
enterTenDigitMobileNumber, but the value only says "Enter mobile number" without specifying the 10-digit requirement. Users won't know the expected format.🔎 Suggested fix
- "enterTenDigitMobileNumber": "Enter mobile number" + "enterTenDigitMobileNumber": "Enter 10-digit mobile number"src/app/app-modules/nurse-doctor/workarea/workarea.component.ts-263-269 (1)
263-269: Add error handling and subscription cleanup for signature check.The subscription to
checkUsersignatureExistlacks error handling. If the API call fails, the user won't be informed anddoctorSignatureFlagwill remainfalsesilently. Additionally, this subscription should be stored and unsubscribed inngOnDestroyto prevent potential memory leaks.🔎 Proposed fix
Add a class property to store the subscription:
signatureCheckSubscription!: Subscription;Then update the subscription:
- this.doctorService + this.signatureCheckSubscription = this.doctorService .checkUsersignatureExist(this.sessionstorage.getItem('userID')) .subscribe((res: any) => { if (res.statusCode === 200 && res.data !== null) { this.doctorSignatureFlag = res.data.signStatus; } - }); + }, + (err: any) => { + console.error('Error checking user signature:', err); + });And clean up in
ngOnDestroy:if (this.signatureCheckSubscription) this.signatureCheckSubscription.unsubscribe();src/app/app-modules/nurse-doctor/visit-details/chief-complaints/chief-complaints.component.html-78-80 (1)
78-80: SuspiciousselectionChangeevent on input field.Line 79 binds
(selectionChange)to an<input>element, butselectionChangeis only fired by<mat-select>components, not standard inputs. This binding has no effect. If duration validation is needed on input changes, use the existing(input)handler on line 78 or consider(blur).🔎 Suggested fix
formControlName="duration" (input)="onInputDuration(complaint)" - (selectionChange)="validateDuration(complaint)" (focus)="trackFieldInteraction('Duration')" />src/app/app-modules/nurse-doctor/case-sheet/general-case-sheet/doctor-diagnosis-case-sheet/doctor-diagnosis-case-sheet.component.ts-439-451 (1)
439-451: Missing error handling ingetUserIdsubscription.If
getUserId()fails (e.g., network error), the error is silently swallowed anddownloadSignwon't proceed. Consider adding error handling to notify or fallback gracefully.🔎 Proposed fix
downloadSign() { this.getUserId().subscribe( userId => { const userIdToUse = this.beneficiaryDetails?.tCSpecialistUserID ?? userId; this.doctorService.downloadSign(userIdToUse).subscribe( (response: any) => { const blob = new Blob([response], { type: response.type }); this.showSign(blob); }, (err: any) => { console.error('Error downloading signature:', err); } ); }, + (err: any) => { + console.error('Error getting user ID:', err); + } ); }src/app/app-modules/nurse-doctor/case-sheet/general-case-sheet/doctor-diagnosis-case-sheet/doctor-diagnosis-case-sheet.component.ts-33-34 (1)
33-34: Remove unused import.The
getimport from 'jquery' appears to be unused in this file.🔎 Proposed fix
-import { get } from 'jquery'; -import { map, Observable } from 'rxjs'; +import { Observable } from 'rxjs'; +import { map } from 'rxjs/operators';src/app/app-modules/data-sync/workarea/workarea.component.ts-94-95 (1)
94-95: Remove debug statements before production release.
console.clear()is particularly problematic as it clears the developer console, hiding potentially useful debugging information from other parts of the application. Theconsole.log(res)is also debug logging that should be removed.🔎 Proposed fix
getDataSYNCGroup() { this.dataSyncService.getDataSYNCGroup().subscribe((res: any) => { - console.clear(); - console.log(res); if (res.statusCode === 200) { this.syncTableGroupList = this.createSyncActivity(res.data); console.log('syncTableGroupList', this.syncTableGroupList); } }); }src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.css-74-76 (1)
74-76: Fix the margin property override.Line 74 sets
margin-top: 10px, but line 75 immediately overrides it withmargin: 0, effectively nullifying the top margin. This appears unintentional.🔎 Proposed fix
.sms-section .alt-phone-field { - margin-top: 10px; margin: 0; + margin-top: 10px; width: 260px; min-width: 180px; }Alternatively, if no top margin is needed:
.sms-section .alt-phone-field { - margin-top: 10px; margin: 0; width: 260px; min-width: 180px; }Committable suggestion skipped: line range outside the PR's diff.
src/app/app.component.ts-46-46 (1)
46-46: Remove or clarify the unusedtrackingServiceinjection.The
trackingServiceis injected in the constructor but never used anywhere in the component or its template. Either remove this unused dependency or add a comment explaining why it's instantiated at the component level.src/app/app-modules/nurse-doctor/case-record/general-case-record/test-and-radiology/test-and-radiology.component.html-72-74 (1)
72-74: Safe navigation operator removed - potential runtime error.Line 73 changed from
component?.testResultValuetocomponent.testResultValue, removing the safe navigation operator. Ifcomponentcan benullorundefined, this will cause a runtime error.Lines 85-87 and 102-104 retain the safe navigation operator (
component?.testResultUnit,component?.remarks), suggesting defensive coding is still needed.🔎 Proposed fix
<div *ngFor="let component of element.componentList"> - {{ component.testResultValue }} + {{ component?.testResultValue }} </div>src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/general-opd-diagnosis/general-opd-diagnosis.component.ts-180-181 (1)
180-181: Fix Prettier formatting issue causing CI failure.The pipeline is failing due to an extra newline on line 181.
🔎 Proposed fix
onDiagnosisInputKeyup(value: string, index: number) { - const term = (value || '').trim();src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/ncd-screening-diagnosis/ncd-screening-diagnosis.component.ts-262-288 (1)
262-288: Potential runaway loop inbootstrapUntilScrollable.The
tryFillfunction usesrequestAnimationFramerecursively without a guaranteed exit whenloadingMore[rowIndex]remainstrue. IffetchPageerrors out and doesn't resetloadingMore, this could spin indefinitely consuming CPU. Consider adding a timeout or maximum retry limit to the waiting logic.Proposed fix with retry limit
private bootstrapUntilScrollable(rowIndex: number, panelEl: HTMLElement) { let fetched = 0; + let waitFrames = 0; + const MAX_WAIT_FRAMES = 60; // ~1 second at 60fps const tryFill = () => { const scrollable = panelEl.scrollHeight > panelEl.clientHeight; if ( scrollable || this.noMore[rowIndex] || fetched >= this.BOOTSTRAP_MAX_PAGES ) return; if (this.loadingMore[rowIndex]) { + if (++waitFrames > MAX_WAIT_FRAMES) return; // prevent infinite wait requestAnimationFrame(tryFill); return; } + waitFrames = 0; fetched++; this.fetchPage(rowIndex, true); requestAnimationFrame(tryFill); };src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.ts-112-126 (1)
112-126: Missing guard for emptyprescribedDrugsarray.If
this.data.prescribedDrugsis empty or undefined, the loop creates an emptyreq_arr, and callingsendSMS([])might produce unexpected backend behavior. Consider validating upfront or disabling the send button when there are no drugs.Proposed fix
sendSMS() { const currentServiceID = this.sessionstorage.getItem('currentServiceID'); - if (currentServiceID !== undefined) { + if (currentServiceID !== undefined && this.data.prescribedDrugs?.length > 0) { this._smsService .getSMStypes(currentServiceID) ... + } else if (!this.data.prescribedDrugs?.length) { + this.snackBar.open('No prescribed drugs to send', 'Close', { + duration: 3000, + verticalPosition: 'top', + }); } }Committable suggestion skipped: line range outside the PR's diff.
🧹 Nitpick comments (37)
src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/pnc-diagnosis/pnc-diagnosis.component.ts (1)
271-272: Consider adding entries before the loop for clarity.The conditional logic inside the loop works correctly but relies on adding exactly one entry per iteration. A clearer approach would be to add all needed entries upfront:
while (provisionalDiagnosisList.length < provisionalDiagnosisDataList.length) { this.addProvisionalDiagnosis(); } for (let i = 0; i < provisionalDiagnosisDataList.length; i++) { provisionalDiagnosisList.at(i).patchValue({...}); // ... }This makes the intent explicit and removes the dependency on per-iteration additions. However, since this pattern matches the confirmatory diagnosis logic (lines 289-292) and appears to be working correctly, this refactor is optional.
src/app/app-modules/nurse-doctor/history/general-opd-history/past-history/past-history.component.html (1)
15-18: Tracking event binding follows sensible patterns.The tracking implementation appropriately uses:
focusevents for text inputs (capturing when users begin data entry)selectionChangeevents for dropdowns (capturing selection changes)clickevents for buttons (capturing explicit actions)This pattern is consistent and aligns with standard telemetry practices.
Also applies to: 52-54, 80-81, 99-100, 113-116, 135-138, 147-150, 191-194, 219-220, 238-239, 252-255, 274-277, 287-289
src/app/app-modules/nurse-doctor/shared/services/doctor.service.ts (1)
2907-2917: Consider URL encoding foruserNameto prevent issues with special characters.If
userNamecontains special characters (spaces,&,?, etc.), the URL may be malformed or cause unexpected behavior. Consider usingencodeURIComponent:🔎 Proposed fix
getUserId(userName: any) { - return this.http.get(environment.getUserId + userName); + return this.http.get(environment.getUserId + encodeURIComponent(userName)); }src/app/app-modules/nurse-doctor/workarea/workarea.component.ts (3)
2486-2502: Add defensive check for array length mismatch in SMSObjectCreation.The method assumes
prescribedDrugIDsarray has the same length asprescriptions. If the API returns fewer IDs than expected (due to partial failures or data inconsistency), accessingprescribedDrugIDs[index]could returnundefined, leading to incomplete SMS data.🔎 Proposed defensive check
SMSObjectCreation( diagnosisList: any, prescriptions: any, prescribedDrugIDs: any ) { + if (prescribedDrugIDs?.length !== prescriptions?.length) { + console.warn('Prescription IDs count mismatch with prescribed drugs'); + } return { diagnosisProvided: diagnosisList?.map((d: any) => d.term).join(', '), prescribedDrugs: prescriptions?.map((p: any, index: number) => ({ beneficiaryRegID: this.beneficiaryRegID, - prescribedDrugID: prescribedDrugIDs[index], + prescribedDrugID: prescribedDrugIDs?.[index], drugName: p.drugName, dosage: `${p.dose} (${p.drugStrength})`, frequency: p.frequency, noOfDays: p.duration, })), }; }
2504-2518: Consider showing a success confirmation after SMS dialog closes.The
sendPrescriptionSmsmethod navigates immediately after the dialog closes without displaying a success confirmation to the user. Other code paths showconfirmationService.alertwith success messages. Consider adding confirmation feedback for consistency with user expectations.🔎 Proposed enhancement
sendPrescriptionSms(prescriptionSmsObject: any) { const dialogRef = this.mdDialog.open(SmsNotificationComponent, { width: '900px', disableClose: true, data: prescriptionSmsObject, }); dialogRef.afterClosed().subscribe(result => { + this.confirmationService.alert( + this.currentLanguageSet.alerts.info.dataSaved || 'Data saved successfully', + 'success' + ); if (this.isSpecialist) { this.router.navigate(['/common/tcspecialist-worklist']); } else { this.router.navigate(['/nurse-doctor/doctor-worklist']); } }); }
2868-2870: Remove unused variable declaration.The
patientVisitFormvariable is declared but never used insubmitCovidCareDiagnosisForm. This appears to be a copy-paste artifact from other methods that do use this variable for SMS creation.🔎 Proposed fix
submitCovidCareDiagnosisForm() { if (this.checkNurseRequirements(this.patientMedicalForm)) { const temp = { beneficiaryRegID: this.beneficiaryRegID, benVisitID: this.visitID, visitCode: this.sessionstorage.getItem('visitCode'), providerServiceMapID: this.sessionstorage.getItem('providerServiceID'), createdBy: this.sessionstorage.getItem('userName'), }; - const patientVisitForm = <FormGroup>( - this.patientMedicalForm.controls['patientCaseRecordForm'] - ); - this.doctorServicesrc/app/app-modules/login/login.component.ts (1)
158-163: Consider removing duplicate setUserId call.The
trackingService.setUserIdis called here (line 158-160) and then again insidegetServicesAuthdetails(line 258), which is invoked immediately after on line 161-163. While this doesn't cause incorrect behavior, the duplicate call is redundant.🔎 Proposed fix to remove duplicate call
.subscribe((userLoggedIn: any) => { if (userLoggedIn.statusCode === 200) { if (userLoggedIn?.data?.previlegeObj[0]) { this.sessionstorage.setItem( 'loginDataResponse', JSON.stringify(userLoggedIn.data) ); - this.trackingService.setUserId( - userLoggedIn.data.userID - ); this.getServicesAuthdetails( userLoggedIn.data );src/app/app-modules/nurse-doctor/case-record/general-case-record/prescription/prescription.component.html (2)
155-156: Missing focus tracking for Unit field.The Unit field has
selectionChangetracking on line 156 but appears to be missing(focus)tracking on line 155, unlike other select fields (e.g., Dosage on lines 93-94). Consider adding focus tracking for consistency:🔎 Suggested addition
name="unit" [(ngModel)]="currentPrescription.unit" [disabled]="!currentPrescription.drugID" - + (focus)="trackFieldInteraction('Unit')" (selectionChange)="trackFieldInteraction('Unit Selection')" required>
167-172: Use named constants to replace magic number form IDs.The quantity field is conditionally hidden for formIDs 1 and 2 across multiple prescription components. This pattern appears intentional and consistent, but the magic numbers lack explanation. Replace
formID !== 1 && formID !== 2with named constants (e.g.,LIQUID_FORM_ID,INJECTION_FORM_ID) or add an inline comment explaining which form types these IDs represent—for example:<!-- Hide quantity for liquid/injection forms (formID 1-2) --> *ngIf=" currentPrescription.formID && currentPrescription.formID !== 1 && currentPrescription.formID !== 2 "This pattern is replicated in
quick-consult.component.htmlandprescribe-tm-medicine.component.htmland should be consistent across all three.src/app/app-modules/data-sync/workarea/workarea.component.html (1)
102-141: Consider extracting inline styles to the component stylesheet.The footer legend uses inline styles for flex layout and margins. While functional, moving these to
workarea.component.csswould improve maintainability.src/app/app-modules/nurse-doctor/quick-consult/quick-consult.component.ts (2)
174-183: Arrays accessed by index without initialization may cause issues.The arrays
loadingMore,noMore,wantMore,pageByIndex,lastQueryByIndex, andsuggestedDiagnosisListare accessed byindexin methods likefetchPage, but they're initialized as empty arrays. Accessingarray[index]whereindexhasn't been set will returnundefined. While JavaScript handles this gracefully, consider initializing these per-index when first accessed or using a default value pattern.
1302-1328: Potential performance concern with recursiverequestAnimationFrameinbootstrapUntilScrollable.When
loadingMore[rowIndex]is true,tryFillschedules itself repeatedly viarequestAnimationFrameuntil loading completes. While bounded byBOOTSTRAP_MAX_PAGES, this creates a tight loop polling the loading state. Consider using thecompletecallback infetchPageto chain the next iteration instead.src/app/app-modules/core/services/http-service.service.ts (1)
22-24: Consider consolidating the dual HttpClient injection.The service injects
HttpClienttwice with different names (_httpandhttp). Line 32 usesthis.httpwhile line 35 usesthis._http. This creates inconsistency and confusion.Consider using a single HttpClient instance throughout:
constructor( - private _http: HttpClient, - private http: HttpClient + private http: HttpClient ) {Then update line 35:
getLanguage(url: string) { - return this._http.get(url); + return this.http.get(url); }Also applies to: 32-32
src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.css (1)
21-22: Remove commented-out code.The commented border-radius properties should either be uncommented if needed or removed to keep the codebase clean.
src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.html (1)
74-74: Add validation to disable Send SMS button.The Send SMS button is always enabled, even when an alternate number is provided but invalid. Consider disabling the button when
altNumis true and the phone number is invalid to prevent erroneous submissions.🔎 Suggested fix
-<button mat-raised-button class="send-btn" (click)="sendSMS()"> +<button mat-raised-button class="send-btn" (click)="sendSMS()" [disabled]="altNum && phnNum.invalid"> Send SMS </button>src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts (1)
472-474: Add error handling for tracking failures.The
trackFieldInteractionmethod delegates to the tracking service without error handling. If the tracking service fails, it could potentially disrupt the user experience.🔎 Proposed fix to add defensive error handling
trackFieldInteraction(fieldName: string) { - this.trackingService.trackFieldInteraction(fieldName, 'Findings'); + try { + this.trackingService.trackFieldInteraction(fieldName, 'Findings'); + } catch (error) { + console.error('Tracking error:', error); + // Fail silently to avoid disrupting user experience + } }src/app/app-modules/nurse-doctor/visit-details/visit-details/visit-details.component.ts (1)
295-297: Add error handling for tracking failures.Similar to other components, consider adding defensive error handling to prevent tracking failures from affecting the user experience.
🔎 Proposed fix
trackFieldInteraction(fieldName: string) { - this.trackingService.trackFieldInteraction(fieldName, 'Visit Details'); + try { + this.trackingService.trackFieldInteraction(fieldName, 'Visit Details'); + } catch (error) { + console.error('Tracking error:', error); + } }src/app/app-modules/nurse-doctor/examination/general-opd-examination/systemic-examination/musculoskeletal-system/musculoskeletal-system.component.ts (1)
184-189: Add error handling for tracking failures.Consider wrapping the tracking call in try-catch to prevent exceptions from disrupting the examination workflow.
🔎 Proposed fix
trackFieldInteraction(fieldName: string) { - this.trackingService.trackFieldInteraction( - fieldName, - 'Musculoskeletal System Examination' - ); + try { + this.trackingService.trackFieldInteraction( + fieldName, + 'Musculoskeletal System Examination' + ); + } catch (error) { + console.error('Tracking error:', error); + } }src/app/app-modules/nurse-doctor/examination/general-opd-examination/systemic-examination/central-nervous-system/central-nervous-system.component.html (1)
12-12: Consider debouncing focus events for better performance.The template adds multiple
(focus)event bindings that will fire every time a user focuses on a textarea. For frequently accessed forms, this could generate substantial tracking traffic.Consider implementing debouncing in the component to limit the frequency of tracking calls:
import { debounceTime, Subject } from 'rxjs'; private trackingSubject = new Subject<{field: string, context: string}>(); ngOnInit() { this.trackingSubject .pipe(debounceTime(300)) .subscribe(({field, context}) => { this.trackingService.trackFieldInteraction(field, context); }); } trackFieldInteraction(fieldName: string) { this.trackingSubject.next({field: fieldName, context: 'Central Nervous System Examination'}); }Also applies to: 36-36, 54-54, 72-72, 90-90, 108-108, 122-122, 146-146
src/app/app-modules/nurse-doctor/examination/general-opd-examination/systemic-examination/systemic-examination.component.ts (1)
143-148: Add error handling for tracking failures.Consider defensive error handling to ensure tracking issues don't affect the examination workflow.
🔎 Proposed fix
trackFieldInteraction(fieldName: string) { - this.trackingService.trackFieldInteraction( - fieldName, - 'Systemic Examination' - ); + try { + this.trackingService.trackFieldInteraction( + fieldName, + 'Systemic Examination' + ); + } catch (error) { + console.error('Tracking error:', error); + } }src/app/app-modules/core/components/app-footer/app-footer.component.html (1)
33-35: Consider improving icon accessibility.The mail icon could benefit from an aria-label for screen readers, especially since it's part of an interactive element.
🔎 Suggested improvement
- <mat-icon style="vertical-align: top; font-size: medium; margin-right: 2%" - >mail</mat-icon - > + <mat-icon + style="vertical-align: top; font-size: medium; margin-right: 2%" + aria-label="Feedback" + >mail</mat-icon + >src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.html (4)
126-128: Consider extracting multi-statement event handler to component method.The
optionSelectedevent contains three semicolon-separated method calls. For better maintainability, consider extracting this into a single component method.🔎 Suggested refactor
In the component TypeScript file, add:
onComplaintSelected(event: any, index: number) { this.filterComplaints(event, index); this.getSCTid(event, index); this.trackFieldInteraction('Chief Complaint Selection'); }Then update the template:
<mat-autocomplete #auto="matAutocomplete" [displayWith]="displayChiefComplaint" - (optionSelected)=" - filterComplaints($event, i); getSCTid($event, i); trackFieldInteraction('Chief Complaint Selection') - "> + (optionSelected)="onComplaintSelected($event, i)">
180-180: Consider extracting multi-statement event handler to component method.The
selectionChangeevent contains two semicolon-separated method calls. For better maintainability, consider extracting this into a single component method.🔎 Suggested refactor
In the component TypeScript file, add:
onUnitOfDurationChange(complaint: any) { this.validateDuration(complaint); this.trackFieldInteraction('Unit Of Duration'); }Then update the template:
<mat-select class="input-full-width mat_label_fix" name="unitOfDuration" formControlName="unitOfDuration" [disabled]="!complaint.value.duration" - (selectionChange)="validateDuration(complaint); trackFieldInteraction('Unit Of Duration')"> + (selectionChange)="onUnitOfDurationChange(complaint)">
213-213: Consider extracting multi-statement event handler to component method.The click event contains two semicolon-separated method calls. For consistency with other refactoring suggestions, consider extracting this into a single component method.
🔎 Suggested refactor
In the component TypeScript file, add:
onRemoveComplaint(index: number, complaint: any) { this.removeCheifComplaint(index, complaint); this.trackFieldInteraction('Remove Complaint Button'); }Then update the template:
<button mat-mini-fab [id]="'removeBtn' + i" *ngIf="i !== 0 || (i === 0 && complaint.touched)" - (click)="removeCheifComplaint(i, complaint); trackFieldInteraction('Remove Complaint Button')" + (click)="onRemoveComplaint(i, complaint)" color="warn" style="margin-right: 3px" class="mat_warn_circle">
224-224: Consider extracting multi-statement event handler to component method.The click event contains two semicolon-separated method calls. For consistency with other refactoring suggestions, consider extracting this into a single component method.
🔎 Suggested refactor
In the component TypeScript file, add:
onAddComplaint() { this.addCheifComplaint(); this.trackFieldInteraction('Add Complaint Button'); }Then update the template:
<button mat-mini-fab [id]="'addBtn' + i" *ngIf="isLast" [disabled]="checkComplaintFormValidity(complaint)" - (click)="addCheifComplaint(); trackFieldInteraction('Add Complaint Button')" + (click)="onAddComplaint()" color="primary" class="mat_blue_circle">src/app/app-modules/nurse-doctor/examination/general-opd-examination/general-examination/general-examination.component.ts (1)
208-208: Minor style change: type annotation removed.The type annotation for
hideForANCAndQCwas removed. This is acceptable as TypeScript infers the type from the initialization, but for consistency, you may want to verify whether your team's coding guidelines prefer explicit type annotations for class properties.src/app/app-modules/nurse-doctor/smsTemplate/sms-template.service.ts (3)
33-36: Unused dependency injection:httpInterceptis never used.
HttpServiceServiceis injected but all HTTP calls useHttpClientdirectly. Either remove the unused injection or usehttpInterceptif it provides custom interceptor logic (e.g., auth headers, error handling).🔎 Suggested fix: Remove unused injection
export class SmsTemplateService { constructor( - private httpIntercept: HttpServiceService, private http: HttpClient ) {}Or, if
HttpServiceServicewrapsHttpClientwith interceptors, use it instead:export class SmsTemplateService { constructor( - private httpIntercept: HttpServiceService, - private http: HttpClient + private http: HttpServiceService ) {}
38-49: Potential code duplication:getSMStemplatesandgetSMSTemplatesare nearly identical.Both methods call the same endpoint. The only difference is that
getSMStemplatesaccepts an optionalsmsTypeID. Consider consolidating:🔎 Suggested consolidation
- getSMStemplates(providerServiceMapID: any, smsTypeID?: any) { + getSMStemplates(providerServiceMapID: any, smsTypeID?: any): Observable<any> { return this.http.post(environment.getSMStemplates_url, { providerServiceMapID: providerServiceMapID, smsTemplateTypeID: smsTypeID ? smsTypeID : undefined, }); } - - getSMSTemplates(providerServiceMapID: any) { - return this.http.post(environment.getSMStemplates_url, { - providerServiceMapID: providerServiceMapID, - }); - } + // getSMSTemplates can be replaced by getSMStemplates(providerServiceMapID) without the second arg
56-58: Consider adding explicit return type annotations.The service methods implicitly return
Observable<any>. Adding explicit types improves maintainability and IDE support.import { Observable } from 'rxjs'; sendSMS(obj: any): Observable<any> { return this.http.post(environment.sendSMS_url, obj); }src/app/app-modules/nurse-doctor/shared/utility/autocomplete-scroller.directive.ts (2)
57-70: Address linter warning: remove non-null assertion on line 67.While the assertion is logically safe (assigned on line 58), the linter flags it. A minor refactor eliminates the warning.
🔎 Suggested fix
this.ngZone.runOutsideAngular(() => { - this.scrollListener = () => { + const listener = () => { if (panelEl.scrollHeight <= panelEl.clientHeight) return; // no overflow yet const ratio = (panelEl.scrollTop + panelEl.clientHeight) / panelEl.scrollHeight; if (ratio >= this.threshold) { // hop back into Angular so change detection works this.ngZone.run(() => this.nearEnd.emit()); } }; - panelEl.addEventListener('scroll', this.scrollListener!, { + this.scrollListener = listener; + panelEl.addEventListener('scroll', listener, { passive: true, }); });
95-104: Consider documenting the fallback logic for panel resolution.The
getPanelElmethod uses internal Material APIs viaanycast, which may break on future Angular Material updates. A brief comment helps future maintainers understand the fragility.private getPanelEl(): HTMLElement | null { - // Newer Material exposes panel element + // Access internal MatAutocomplete panel element. + // NOTE: This relies on internal Angular Material APIs and may need + // adjustment after Material version upgrades. const anyAc = this.ac as any;src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/general-opd-diagnosis/general-opd-diagnosis.component.ts (1)
305-307: Consider adding user feedback for fetch errors.Currently, errors are only logged to console. Users may not understand why results stop loading.
error: () => { console.error('Error fetching diagnosis data'); + // Optionally show a toast or set an error state + // this.confirmationService.alert('Failed to load diagnosis suggestions', 'error'); },src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/ncd-screening-diagnosis/ncd-screening-diagnosis.component.ts (1)
290-342: Subscription infetchPageis not tracked for cleanup.Each call to
fetchPagecreates a new subscription tomasterdataService.searchDiagnosisBasedOnPageNothat is not tracked. While the stale-query guard at line 306 helps, rapid navigation or component destruction could leave dangling subscriptions.Consider tracking active subscriptions per index and canceling them on new requests or component destruction:
+ private fetchSubs: Subscription[] = []; ... private fetchPage(index: number, append = false) { const term = this.lastQueryByIndex[index]; if (!term) return; ... + this.fetchSubs[index]?.unsubscribe(); - this.masterdataService + this.fetchSubs[index] = this.masterdataService .searchDiagnosisBasedOnPageNo(termAtReq, pageAtReq) .subscribe({...}); }src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.ts (2)
153-160: Console log in production code.The
console.log('charCode', charCode)statement on line 155 should be removed before production release.Proposed fix
allowOnlyNumbers(event: KeyboardEvent) { const charCode = event.which ? event.which : event.keyCode; - console.log('charCode', charCode); if (charCode < 48 || charCode > 57) { event.preventDefault(); } }
1-15: Unused import:ViewChildandMatPaginator.
ViewChildandMatPaginatorare imported but not used in the component. Remove unused imports to keep the code clean.Proposed fix
-import { Component, Inject, ViewChild } from '@angular/core'; +import { Component, DoCheck, Inject, OnInit } from '@angular/core'; ... -import { MatPaginator } from '@angular/material/paginator';src/app/app-modules/nurse-doctor/case-record/general-case-record/diagnosis/ncd-care-diagnosis/ncd-care-diagnosis.component.ts (2)
260-279: Same subscription cleanup concerns apply here.As noted in the review of
ncd-screening-diagnosis.component.ts, the subscriptions infetchPageare not tracked for cleanup. Consider applying the same fix pattern to track and cancel subscriptions on component destruction or when new requests supersede old ones.Also applies to: 342-394
314-340: SamebootstrapUntilScrollableloop concern applies.The recursive
requestAnimationFramepattern has the same potential for spinning indefinitely ifloadingMorenever resets. Consider adding the retry limit safeguard suggested forncd-screening-diagnosis.component.ts.
| ) { | ||
| const storedLang = localStorage.getItem('appLanguage'); | ||
| this.language = storedLang ? JSON.parse(storedLang) : null; | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Add error handling for localStorage JSON parsing.
The constructor parses localStorage.getItem('appLanguage') without error handling. If the stored value is corrupted or invalid JSON, this will throw an exception and break service initialization.
🔎 Proposed fix
constructor(
private _http: HttpClient,
private http: HttpClient
) {
const storedLang = localStorage.getItem('appLanguage');
- this.language = storedLang ? JSON.parse(storedLang) : null;
+ try {
+ this.language = storedLang ? JSON.parse(storedLang) : null;
+ } catch (e) {
+ console.error('Failed to parse stored language, resetting', e);
+ this.language = null;
+ localStorage.removeItem('appLanguage');
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ) { | |
| const storedLang = localStorage.getItem('appLanguage'); | |
| this.language = storedLang ? JSON.parse(storedLang) : null; | |
| } | |
| ) { | |
| const storedLang = localStorage.getItem('appLanguage'); | |
| try { | |
| this.language = storedLang ? JSON.parse(storedLang) : null; | |
| } catch (e) { | |
| console.error('Failed to parse stored language, resetting', e); | |
| this.language = null; | |
| localStorage.removeItem('appLanguage'); | |
| } | |
| } |
🤖 Prompt for AI Agents
In @src/app/app-modules/core/services/http-service.service.ts around lines 25 -
28, The constructor in HttpServiceService calls JSON.parse on
localStorage.getItem('appLanguage') without protecting against invalid JSON;
wrap the parse in a try/catch around the retrieval of
localStorage.getItem('appLanguage') inside the constructor, assign this.language
= null on parse failure (or when value is null), and log or remove the corrupted
key (e.g., console.error or localStorage.removeItem('appLanguage')) so service
initialization doesn't throw; reference the constructor,
localStorage.getItem('appLanguage'), JSON.parse, and this.language when making
the change.
| import { AmritTrackingService } from 'Common-UI/src/tracking'; | ||
|
|
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# Find and examine the AmritTrackingService
fd -t f "tracking" --extension ts | head -20Repository: PSMRI/MMU-UI
Length of output: 38
🏁 Script executed:
# Examine the findings.component.ts file to see what's being tracked
find . -name "findings.component.ts" -type fRepository: PSMRI/MMU-UI
Length of output: 153
🏁 Script executed:
# Search for where AmritTrackingService is used in the codebase
rg "AmritTrackingService" -t ts --max-count 20Repository: PSMRI/MMU-UI
Length of output: 7516
🏁 Script executed:
# Look for privacy-related configurations or consent mechanisms
rg -i "consent|privacy|gdpr|hipaa" -t ts --max-count 30Repository: PSMRI/MMU-UI
Length of output: 38
🏁 Script executed:
cat -n src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts | head -120Repository: PSMRI/MMU-UI
Length of output: 4826
🏁 Script executed:
cat -n src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts | sed -n '50,60p'Repository: PSMRI/MMU-UI
Length of output: 697
🏁 Script executed:
cat -n src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts | sed -n '100,110p'Repository: PSMRI/MMU-UI
Length of output: 507
🏁 Script executed:
cat -n src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts | sed -n '468,478p'Repository: PSMRI/MMU-UI
Length of output: 263
🏁 Script executed:
# Get total line count to understand file size
wc -l src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.tsRepository: PSMRI/MMU-UI
Length of output: 155
🌐 Web query:
GDPR requirements for user interaction tracking in healthcare applications consent
💡 Result:
Short answer — key GDPR requirements when tracking user interactions in healthcare apps (analytics, behavioural/ad interaction tracking):
-
Health data = special-category data — generally prohibited unless a condition in Article 9 applies (explicit consent is one such condition). [1]
-
If you rely on consent for tracking that processes or infers health data, consent must be valid and “explicit”: freely given, specific, informed, unambiguous (affirmative opt‑in), withdrawable, and typically expressed by a clear statement (separate from other consents). Be careful: consent may be invalid if there is a clear imbalance of power. [2][3]
-
Consider alternative Article 9 grounds before using consent (e.g., processing for provision of health care under Article 9(2)(h), public‑interest/ research grounds) — these have their own strict conditions and Member‑State rules. [1][3]
-
DPIA / high‑risk assessment: tracking in health apps is likely to trigger a Data Protection Impact Assessment (systematic monitoring, special‑category data, profiling or large‑scale processing). Conduct a DPIA before processing and consult the supervisory authority if residual high risks remain. [4]
-
Implement and document technical & organisational safeguards: data minimisation, purpose limitation, pseudonymisation/encryption, retention limits, secure processor contracts (if using third‑party analytics), user rights support (access, rectification, erasure, portability, withdraw consent), and transparent privacy notices (what is tracked, purposes, legal basis, retention, third parties). Keep records to demonstrate compliance. [4][5]
If you want, I can: (a) draft explicit‑consent UI text for an app analytics flow, (b) outline a DPIA checklist for your specific tracking features, or (c) check Member‑State rules that may further restrict health data processing.
Sources: GDPR Article 9 (processing of special categories). [1] ICO guidance on explicit consent and when consent is appropriate. [2] EDPB guidance/opinions on consent and “consent or pay” / imbalance of power concerns. [3] EU / supervisory‑authority guidance on DPIAs (Article 35). [4] ICO / EU guidance on DPIAs, transparency and safeguards. [5]
References:
[1] GDPR Article 9 — Processing of special categories of personal data.
[2] ICO: What are the conditions for processing special category data; when is consent appropriate.
[3] EDPB opinions/guidance on consent (explicit consent, imbalance of power; consent models).
[4] European Commission / EDPB guidance on DPIAs (Article 35).
[5] ICO / EU guidance on transparency, security and contractual obligations for processors.
🌐 Web query:
HIPAA compliance for user behavior tracking in EHR systems
💡 Result:
Short summary — key HIPAA requirements and practical steps for tracking user behavior in EHRs
Legal/technical requirements
- Implement audit controls that record and examine activity in systems containing ePHI (HIPAA Security Rule §164.312(b)). Regularly review those logs. [1][4]
- Enforce access controls and role-based access so only authorized users can view ePHI (§164.312(a)). Apply the Minimum Necessary principle when using behavior data. [1][4]
- Treat any vendor or analytics provider that collects/hosts behavior logs as a business associate (BA) and have a BA agreement that limits uses/disclosures and requires safeguards. [1][4]
- Protect logs as ePHI (confidentiality, integrity, availability): strong access restriction, encryption at rest/in transit, integrity checks, backup and retention policies. [1][4]
Operational best practices
- Log user identity, timestamp, patient/record identifier (or a reversible pseudonym), action performed, source IP/device, and reason/context when feasible. Use risk analysis to decide exact fields and retention. [3][4]
- Limit who can query or export logs; add separation-of-duties and justification/approval workflows for investigations. [3]
- Automate alerting for anomalous access patterns (bulk access, off-hours, privileged-user spikes) and document investigation steps. [3]
- Retain audit trails per your risk analysis and state law; ensure tamper-evidence and ability to produce logs for investigations and breach response. [1][3]
Privacy risk reduction
- Use pseudonymization or de‑identification of behavior data for analytics when individual-level identity is not required. Maintain re‑identification controls when pseudonyms are reversible. [1]
- Apply Minimum Necessary: restrict behavioral reporting to role-appropriate summaries or aggregated metrics unless a specific clinical/administrative need exists. [1]
Third parties, cloud, and analytics vendors
- Require BA agreements that: (a) prohibit uses beyond permitted healthcare operations; (b) require security safeguards, logging, breach notification; (c) allow audits/assessments. Limit downstream sharing. [1]
- Verify vendor security posture (encryption, logging, SOC reports, vulnerability testing). Recent HHS proposals increase vendor oversight and require stronger controls (MFA, inventories, annual audits) — plan to adopt these controls. [2]
Emerging rulemaking (important to watch)
- HHS proposed updates to the Security Rule (NPRM Jan 2025) that would tighten requirements (mandatory inventories, MFA, encryption, annual audits, stricter access-termination timelines). If finalized, these will affect logging and monitoring programs — monitor HHS/OCR rulemaking and implement early where possible. [2]
Practical checklist (implementation)
- Record required audit fields; protect logs with encryption and strict access control. [3][4]
- Define retention and review cadence in policy; perform periodic and post-incident reviews. [1][3]
- Put BA agreements and vendor assessments in place. [1]
- Apply Minimum Necessary and pseudonymize for analytics. [1]
If you want, I can:
- draft an audit-log schema for your EHR (fields, retention, risk-mapping), or
- create a short vendor-BA checklist you can use in procurement.
Sources
- HHS HIPAA Audit Protocol / Audit Controls & Access Control guidance. [HHS]. [4]
- Reuters summary of HHS Jan 6, 2025 NPRM to update the HIPAA Security Rule. [2]
- Research on using EHR audit logs and recommended log fields/practices (PubMed/PMC). [3]
- HHS OIG report on OCR HIPAA audit program (recommendations on audit/enforcement). [1]
Verify privacy and compliance mechanisms are in place for field-level user interaction tracking.
AmritTrackingService tracks field-level interactions on sensitive health data (chief complaints, diagnoses, examination findings). Ensure:
- GDPR compliance: Explicit, freely-given, informed consent (separate from general app terms) is required before tracking health data. A Data Protection Impact Assessment (DPIA) should document the processing. Consent cannot be conditional on app access.
- HIPAA compliance: Audit controls must record all interactions with ePHI. Any vendor handling logs must be a Business Associate with a signed BA agreement. Logs must be encrypted at rest and in transit. Apply the Minimum Necessary principle—use pseudonymization for analytics where individual identity is not required.
- Privacy notice: A transparent privacy notice must disclose what data is tracked, for what purposes, retention periods, and which parties have access.
- Data minimization: Confirm only necessary field-level data is collected; consider tracking aggregated metrics or role-appropriate summaries instead of individual interactions.
Note: This applies across multiple components. Consider addressing tracking compliance at the application level rather than component-by-component.
Also applies to: 104-104, 472-474
🤖 Prompt for AI Agents
In
@src/app/app-modules/nurse-doctor/case-record/general-case-record/findings/findings.component.ts
around lines 55 - 56, The code imports and likely uses AmritTrackingService to
track sensitive field-level interactions (ePHI); update FindingsComponent (and
any components using AmritTrackingService) to enforce a centralized
privacy-and-compliance gating layer: require explicit, recorded user consent
before enabling AmritTrackingService for health fields, consult/add a DPIA entry
for this processing, ensure audit events are stored via an encrypted,
access-controlled audit pipeline (encrypt at rest/in transit and use a
BA-approved vendor), apply pseudonymization/minimum-necessary transformations
before sending analytics (aggregate or role-scoped summaries where possible),
include retention and access details in the app privacy notice, and move these
checks into a shared tracking wrapper/service so components call a
consent-and-compliance-checked API rather than using AmritTrackingService
directly.
| (change)="validateDuration(pastIllness)" | ||
| (focus)="trackFieldInteraction('Duration')" /> |
There was a problem hiding this comment.
Disambiguate tracking labels for illness vs surgery fields.
The tracking labels 'Duration' (lines 100, 239) and 'Time Period Unit' (lines 115, 254) are used in both the Past Illness and Past Surgery sections, making it impossible to distinguish which section the user interacted with in analytics data.
🔎 Suggested fix: Use prefixed labels
formControlName="timePeriodAgo"
(change)="validateDuration(pastIllness)"
-(focus)="trackFieldInteraction('Duration')" />
+(focus)="trackFieldInteraction('Past Illness Duration')" /> (selectionChange)="
validateDuration(pastIllness);
- trackFieldInteraction('Time Period Unit')
+ trackFieldInteraction('Past Illness Time Period Unit')
"> formControlName="timePeriodAgo"
(change)="validateDuration(pastSurgery)"
-(focus)="trackFieldInteraction('Duration')" />
+(focus)="trackFieldInteraction('Past Surgery Duration')" /> (selectionChange)="
validateDuration(pastSurgery);
- trackFieldInteraction('Time Period Unit')
+ trackFieldInteraction('Past Surgery Time Period Unit')
">Also applies to: 113-116, 238-239, 252-255
🤖 Prompt for AI Agents
In
@src/app/app-modules/nurse-doctor/history/general-opd-history/past-history/past-history.component.html
around lines 99 - 100, The analytics tracking labels for duration and time-unit
fields are ambiguous because both Past Illness and Past Surgery use the same
labels; update the calls to trackFieldInteraction in the template (where
validateDuration(pastIllness) and similar handlers are used) to pass distinct
labels prefixed by section (e.g., "PastIllness: Duration", "PastIllness: Time
Period Unit" and analogous "PastSurgery: Duration", "PastSurgery: Time Period
Unit") so analytics can distinguish sections; ensure every occurrence referenced
in the diff (the trackFieldInteraction invocations around validateDuration and
the time unit select) is updated consistently.
| *ngIf=" | ||
| diagnosis.get('provisionalDiagnosisList')?.disabled || | ||
| i !== 0 || |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for diagnosis form group initialization and provisionalDiagnosisList references
rg -n "provisionalDiagnosisList" --type ts -B 5 -A 5 src/app/app-modules/nurse-doctor/quick-consult/Repository: PSMRI/MMU-UI
Length of output: 6686
🏁 Script executed:
#!/bin/bash
# Also search for where the diagnosis form group is created/initialized
rg -n "new FormGroup|new FormArray" --type ts -B 3 -A 10 src/app/app-modules/nurse-doctor/quick-consult/ | head -100Repository: PSMRI/MMU-UI
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Look for the component file to understand the structure
find src/app/app-modules/nurse-doctor/quick-consult -name "*.ts" -type fRepository: PSMRI/MMU-UI
Length of output: 208
🏁 Script executed:
#!/bin/bash
# Find where initProvisionalDiagnosisList is defined
rg -n "initProvisionalDiagnosisList" --type ts -B 2 -A 15 src/Repository: PSMRI/MMU-UI
Length of output: 45415
🏁 Script executed:
#!/bin/bash
# Look at the quick-consult component HTML around lines 643-645 for more context
sed -n '630,660p' src/app/app-modules/nurse-doctor/quick-consult/quick-consult.component.htmlRepository: PSMRI/MMU-UI
Length of output: 1404
Fix the condition logic on the remove button.
The condition diagnosis.get('provisionalDiagnosisList')?.disabled attempts to access a control named provisionalDiagnosisList within the individual diagnosis form group, but this control does not exist. The individual diagnosis form group only contains conceptID, term, and provisionalDiagnosis controls. The provisionalDiagnosisList is a top-level FormArray in the parent form, not a nested control within each diagnosis group. This condition needs to be corrected to reference the actual controls available in the diagnosis form group.
🤖 Prompt for AI Agents
In @src/app/app-modules/nurse-doctor/quick-consult/quick-consult.component.html
around lines 643 - 645, The remove-button condition wrongly checks
diagnosis.get('provisionalDiagnosisList')?.disabled (a non-existent child
control); change it to reference the actual top-level FormArray's disabled state
instead (e.g., use the parent form or the provisionalDiagnosisList FormArray:
parentForm.get('provisionalDiagnosisList')?.disabled or
provisionalDiagnosisList?.disabled) while keeping the other checks (i !== 0 ||
...); note that each diagnosis FormGroup only has conceptID, term, and
provisionalDiagnosis, so do not attempt to access provisionalDiagnosisList from
diagnosis.
| </div> | ||
|
|
||
| <!-- Pagination --> | ||
| <mat-paginator [pageSize]="5" [pageSizeOptions]="[5, 10, 25]" showFirstLastButtons></mat-paginator> |
There was a problem hiding this comment.
Paginator not connected to table data.
The mat-paginator is defined but the prescription table uses *ngFor directly on data.prescribedDrugs without a MatTableDataSource. The paginator will render but won't actually paginate the table. To fix this, either:
- Remove the paginator if not needed, or
- Bind the table to a
MatTableDataSourceand connect it to the paginator.
🔎 Example fix to wire the paginator
In the component TypeScript file, create a data source:
dataSource = new MatTableDataSource<any>(this.data.prescribedDrugs);
@ViewChild(MatPaginator) paginator!: MatPaginator;
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
}Then update the template to use mat-table instead of HTML table:
<table mat-table [dataSource]="dataSource" class="mat-elevation-z4">
<!-- columns definition -->
</table>🤖 Prompt for AI Agents
In
@src/app/app-modules/nurse-doctor/sms-notification/sms-notification.component.html
at line 48, The paginator is not wired to the table because the template uses
*ngFor over data.prescribedDrugs instead of a MatTableDataSource; replace the
direct *ngFor table with an Angular Material table bound to a MatTableDataSource
(e.g., create a dataSource = new
MatTableDataSource<any>(this.data.prescribedDrugs)), add
@ViewChild(MatPaginator) paginator!: MatPaginator, and in ngAfterViewInit assign
this.dataSource.paginator = this.paginator so the mat-paginator controls paging;
alternatively remove the mat-paginator if pagination is not required.
| [disabled]="rbsResultChange()" | ||
| (focus)="trackFieldInteraction('RBS Test Result')" /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for rbsResultChange implementation in cancer-patient-vitals component
fd 'cancer-patient-vitals.component.ts' -type f | head -5Repository: PSMRI/MMU-UI
Length of output: 226
🏁 Script executed:
#!/bin/bash
# Get the implementation of rbsResultChange
rg -nP -A15 'rbsResultChange\s*\(' src/app/app-modules/nurse-doctor/vitals/cancer-patient-vitals/ --type=tsRepository: PSMRI/MMU-UI
Length of output: 4189
🏁 Script executed:
#!/bin/bash
# Check the HTML file to verify lines 696-697 and 725-726
wc -l src/app/app-modules/nurse-doctor/vitals/cancer-patient-vitals/cancer-patient-vitals.component.htmlRepository: PSMRI/MMU-UI
Length of output: 158
🏁 Script executed:
#!/bin/bash
# Get the complete rbsResultChange method
rg -nP -A30 'rbsResultChange\s*\(\)\s*:\s*boolean' src/app/app-modules/nurse-doctor/vitals/cancer-patient-vitals/cancer-patient-vitals.component.tsRepository: PSMRI/MMU-UI
Length of output: 1361
🏁 Script executed:
#!/bin/bash
# Check the HTML lines mentioned in the review
sed -n '690,700p' src/app/app-modules/nurse-doctor/vitals/cancer-patient-vitals/cancer-patient-vitals.component.html
sed -n '720,730p' src/app/app-modules/nurse-doctor/vitals/cancer-patient-vitals/cancer-patient-vitals.component.htmlRepository: PSMRI/MMU-UI
Length of output: 861
Remove the rbsResultChange() call from the [disabled] binding.
The rbsResultChange() method has side effects—it modifies service state via setRbsInCurrentVitals() and manipulates form control state (enable()/disable()). Calling it in a template binding causes these side effects to execute on every change detection cycle, which violates Angular best practices and can cause unexpected behavior.
Refactor to use a boolean property that's updated when the form value changes, or call rbsResultChange() in a component lifecycle hook or event handler instead of the template binding.
Also applies to: 725-726
| (focus)="trackFieldInteraction('Waist Circumference')" | ||
| [required]="benAge >= 30 && visitCategory === 'NCD screening'" /> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify validation error handling for required waist circumference field
rg -n "waistCircumference" --type=ts -g "*general-patient-vitals.component.ts" -A 5 -B 5Repository: PSMRI/MMU-UI
Length of output: 7622
🏁 Script executed:
#!/bin/bash
# Check context around validation error handling
rg -n "checkNurseRequirements|required\.push" --type=ts -g "*general-patient-vitals.component.ts" -A 2 -B 2 | head -100Repository: PSMRI/MMU-UI
Length of output: 11995
🏁 Script executed:
#!/bin/bash
# Check if there's any age-based condition for waistCircumference validation
rg -n "benAge.*waistCircumference|waistCircumference.*benAge" --type=ts -g "*general-patient-vitals.component.ts"Repository: PSMRI/MMU-UI
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Check the validation setter/validation logic for waistCircumference field
rg -n "setValidators|updateValueAndValidity" --type=ts -g "*general-patient-vitals.component.ts" -A 3 -B 3 | grep -A 5 -B 5 "waistCircumference"Repository: PSMRI/MMU-UI
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Check the specific lines in the HTML file where the required attribute is set
sed -n '240,255p' src/app/app-modules/nurse-doctor/vitals/general-patient-vitals/general-patient-vitals.component.htmlRepository: PSMRI/MMU-UI
Length of output: 776
🏁 Script executed:
#!/bin/bash
# Check form initialization and validator setup for waistCircumference
rg -n "waistCircumference_cm.*Validators|patientVitalsForm.*waistCircumference" --type=ts -g "*general-patient-vitals.component.ts" -B 2 -A 2Repository: PSMRI/MMU-UI
Length of output: 683
🏁 Script executed:
#!/bin/bash
# Check for any conditional validator logic based on age or visitCategory
rg -n "benAge|visitCategory.*waist" --type=ts -g "*general-patient-vitals.component.ts" -B 3 -A 3Repository: PSMRI/MMU-UI
Length of output: 5047
🏁 Script executed:
#!/bin/bash
# Look for form control initialization to understand how validators are applied
rg -n "formGroup.*waistCircumference|patchValue.*waistCircumference|setValue.*waistCircumference" --type=ts -g "*general-patient-vitals.component.ts" -B 5 -A 5Repository: PSMRI/MMU-UI
Length of output: 38
🏁 Script executed:
#!/bin/bash
# Check the checkIDRSForWaist method to understand age-based logic
rg -n "checkIDRSForWaist" --type=ts -g "*general-patient-vitals.component.ts" -A 10Repository: PSMRI/MMU-UI
Length of output: 1494
🏁 Script executed:
#!/bin/bash
# Search for any documentation or comments about NCD screening age requirements
rg -n "NCD.*screening|age.*30|waist.*requirement" --type=ts --type=html -g "*general-patient-vitals*" -i -B 2 -A 2 | head -50Repository: PSMRI/MMU-UI
Length of output: 6261
🏁 Script executed:
#!/bin/bash
# Check if there's any README or documentation about NCD screening requirements
find . -type f \( -name "README*" -o -name "*.md" \) -exec grep -l "NCD\|screening" {} \;Repository: PSMRI/MMU-UI
Length of output: 38
Fix validation logic gap for age-conditional waist circumference requirement.
The [required] attribute in HTML (line 248) applies only when benAge >= 30 && visitCategory === 'NCD screening', but the validation in checkNurseRequirements() (lines 296-301 in component.ts) checks for waist circumference errors whenever visitCategory === 'NCD screening' without the age condition. This creates a mismatch: patients under 30 in NCD screening won't see the field as required but validation errors may still be enforced. Update checkNurseRequirements() to include the benAge >= 30 condition, or clarify if waist circumference should be mandatory for all NCD screening patients regardless of age. Additionally, the validation error message references vitalsCancerscreening_QC.waistCircumference which appears to be from a different screening context—ensure the error message label aligns with NCD screening workflows.
🤖 Prompt for AI Agents
In
@src/app/app-modules/nurse-doctor/vitals/general-patient-vitals/general-patient-vitals.component.html
around lines 247 - 248, The validation in checkNurseRequirements() is too broad:
narrow the waist circumference check so it only runs when visitCategory === 'NCD
screening' AND benAge >= 30 (to match the template's [required]="benAge >= 30 &&
visitCategory === 'NCD screening'"); update the error label reference from
vitalsCancerscreening_QC.waistCircumference to the correct NCD screening field
name used elsewhere (e.g., vitalsNCDscreening_QC.waistCircumference or the
module's NCD-specific label) so the error message aligns with the NCD workflow.
| if (prescribedDrugs.length > 0) { | ||
| const prescriptionSmsObject = this.SMSObjectCreation( | ||
| JSON.parse( | ||
| JSON.stringify( | ||
| ( | ||
| this.patientVisitForm.get( | ||
| 'generalDiagnosisForm.provisionalDiagnosisList' | ||
| ) as FormArray | ||
| ).value | ||
| ) | ||
| ), | ||
| prescribedDrugs, | ||
| res.data.prescribedDrugIDs | ||
| ); | ||
| this.sendPrescriptionSms(prescriptionSmsObject); |
There was a problem hiding this comment.
Critical: Wrong form reference causes null pointer exception in PNC SMS flow.
At line 3109, this.patientVisitForm is used to access generalDiagnosisForm.provisionalDiagnosisList, but this.patientVisitForm refers to patientVisitForm (visit details), not patientCaseRecordForm (which contains the diagnosis forms). This will cause a runtime error when .value is accessed on null.
Compare with submitGeneralOPDDiagnosisForm (lines 3031-3033) which correctly creates a local reference to patientCaseRecordForm.
🔎 Proposed fix
submitPNCDiagnosisForm() {
if (this.checkNurseRequirements(this.patientMedicalForm)) {
const temp = {
beneficiaryRegID: this.beneficiaryRegID,
benVisitID: this.visitID,
visitCode: this.sessionstorage.getItem('visitCode'),
providerServiceMapID: this.sessionstorage.getItem('providerServiceID'),
createdBy: this.sessionstorage.getItem('userName'),
};
+ const patientCaseRecordForm = <FormGroup>(
+ this.patientMedicalForm.controls['patientCaseRecordForm']
+ );
+
const prescribedDrugs = this.getLabandPrescriptionData();
this.doctorService
.postDoctorPNCDetails(
this.patientMedicalForm,
temp,
this.schedulerData,
this.doctorSignatureFlag
)
.subscribe(
(res: any) => {
if (res.statusCode === 200 && res.data !== null) {
this.patientMedicalForm.reset();
this.removeBeneficiaryDataForDoctorVisit();
if (prescribedDrugs.length > 0) {
const prescriptionSmsObject = this.SMSObjectCreation(
JSON.parse(
JSON.stringify(
(
- this.patientVisitForm.get(
+ patientCaseRecordForm.get(
'generalDiagnosisForm.provisionalDiagnosisList'
) as FormArray
).value
)
),
prescribedDrugs,
res.data.prescribedDrugIDs
);
this.sendPrescriptionSms(prescriptionSmsObject);
} else {🤖 Prompt for AI Agents
In @src/app/app-modules/nurse-doctor/workarea/workarea.component.ts around lines
3104 - 3118, The code is using the wrong form reference: replace uses of
this.patientVisitForm when building the provisionalDiagnosisList for SMS with
the patientCaseRecordForm instance (as done in submitGeneralOPDDiagnosisForm) so
you don't call .value on null; specifically, obtain the FormArray value from the
patientCaseRecordForm (the generalDiagnosisForm.provisionalDiagnosisList) before
calling SMSObjectCreation, then pass that value into SMSObjectCreation and
continue to call sendPrescriptionSms with the resulting prescriptionSmsObject;
update references around SMSObjectCreation and ensure the local variable name
matches the pattern used elsewhere (e.g., patientCaseRecordForm) to avoid null
pointer exceptions.
| "enterMobileNumberToBeLinkedWithAbha": "Enter Phone number to be linked with ABHA", | ||
| "doYouWantToVerifyMobileOtpForAbha": "Your provided mobile number is not linked with Aadhaar, Do you want to verify it?", | ||
| "abhaCardAlreadyExists": "ABHA already exists for the Aadhaar Number", | ||
| "enterABHANumber": "Please Enter ABHA Number", | ||
| "enterABHAAddress": "Please Enter ABHA Address", | ||
| "enterAadhaarNumber": "Please Enter Aadhaar Number", | ||
| "enterMobileNumber": "Please Enter Mobile Number", | ||
| "enterCorrectAuthIdForAuthMode": "Please Enter correct Authentication ID for choosen AuthMode", | ||
| "abhaAddressFound" : "ABHA Address Found:", | ||
| "searchAndDownloadAbha": "Search and Download ABHA", | ||
| "abhaSearchMode": "ABHA Search Mode*", | ||
| "verifyAbha": "Verify ABHA", | ||
| "issueInAbhaCard": "Issue in printing ABHA Card", | ||
| "fileUploadedSuccessfully": "File Uploaded successfully", | ||
| "verifyMobileOtp": "Verify Mobile OTP", | ||
| "enterMobileOtp": "Enter Mobile OTP", | ||
| "verify": "Verify", | ||
| "abhaNumberAlreadyWith": "The Abha number is already linked with beneficiary ID - ", |
There was a problem hiding this comment.
Complete the ABHA-related Assamese translations.
These 18 ABHA keys are showing English text instead of Assamese translations. This creates an inconsistent experience for Assamese-speaking users when they interact with ABHA features.
If this is intentional for a phased rollout, please add a TODO comment. Otherwise, these strings should be translated before release.
🤖 Prompt for AI Agents
In @src/assets/Assamese.json around lines 1724 - 1741, Several ABHA-related i18n
keys (enterMobileNumberToBeLinkedWithAbha, doYouWantToVerifyMobileOtpForAbha,
abhaCardAlreadyExists, enterABHANumber, enterABHAAddress, enterAadhaarNumber,
enterMobileNumber, enterCorrectAuthIdForAuthMode, abhaAddressFound,
searchAndDownloadAbha, abhaSearchMode, verifyAbha, issueInAbhaCard,
fileUploadedSuccessfully, verifyMobileOtp, enterMobileOtp, verify,
abhaNumberAlreadyWith) are still in English; replace each English value with the
appropriate Assamese translation so the UI is consistent, or if leaving them in
English is intentional for a staged rollout, add a clear TODO comment next to
each key indicating why and when the Assamese translations will be added. Ensure
you update the exact JSON entries for those keys (matching the key names above)
and keep JSON syntax valid.
| "enterMobileNumberToBeLinkedWithAbha": "Enter Phone number to be linked with ABHA", | ||
| "doYouWantToVerifyMobileOtpForAbha": "Your provided mobile number is not linked with Aadhaar, Do you want to verify it?", | ||
| "abhaCardAlreadyExists": "ABHA already exists for the Aadhaar Number", | ||
| "enterABHANumber": "Please Enter ABHA Number", | ||
| "enterABHAAddress": "Please Enter ABHA Address", | ||
| "enterAadhaarNumber": "Please Enter Aadhaar Number", | ||
| "enterMobileNumber": "Please Enter Mobile Number", | ||
| "enterCorrectAuthIdForAuthMode": "Please Enter correct Authentication ID for choosen AuthMode", | ||
| "abhaAddressFound" : "ABHA Address Found:", | ||
| "searchAndDownloadAbha": "Search and Download ABHA", | ||
| "abhaSearchMode": "ABHA Search Mode*", | ||
| "verifyAbha": "Verify ABHA", | ||
| "issueInAbhaCard": "Issue in printing ABHA Card", | ||
| "fileUploadedSuccessfully": "File Uploaded successfully", | ||
| "verifyMobileOtp": "Verify Mobile OTP", | ||
| "enterMobileOtp": "Enter Mobile OTP", | ||
| "verify": "Verify", | ||
| "abhaNumberAlreadyWith": "The Abha number is already linked with beneficiary ID - ", | ||
| "enterTenDigitMobileNumber": "Enter mobile number" |
There was a problem hiding this comment.
Missing Hindi translations for ABHA keys—blocks Hindi user experience.
The new ABHA-related keys contain English text instead of Hindi translations. This is a localization defect that breaks the language experience for Hindi-speaking users.
Examples of untranslated keys:
- Line 1727:
"enterMobileNumberToBeLinkedWithAbha": "Enter Phone number to be linked with ABHA" - Line 1728:
"doYouWantToVerifyMobileOtpForAbha": "Your provided mobile number is not linked with Aadhaar, Do you want to verify it?" - Lines 1729-1745: Similar pattern—all values are in English
Expected: All values should be translated to Hindi (Devanagari script) to match the rest of the file and provide a consistent user experience.
Based on learnings, ensure translations are completed before merging i18n changes to avoid breaking the localized user experience.
Sample Hindi translations needed
For reference, these keys need proper Hindi translations similar to existing patterns in the file. For example:
enterMobileNumberToBeLinkedWithAbha→ "ABHA से जोड़ने के लिए फोन नंबर दर्ज करें"verify→ "सत्यापित करें"
All 19 keys in this section require similar treatment.
🤖 Prompt for AI Agents
In @src/assets/Hindi.json around lines 1727 - 1745, Several ABHA-related
localization entries (e.g., enterMobileNumberToBeLinkedWithAbha,
doYouWantToVerifyMobileOtpForAbha, abhaCardAlreadyExists, enterABHANumber,
enterABHAAddress, enterAadhaarNumber, enterMobileNumber,
enterCorrectAuthIdForAuthMode, abhaAddressFound, searchAndDownloadAbha,
abhaSearchMode, verifyAbha, issueInAbhaCard, fileUploadedSuccessfully,
verifyMobileOtp, enterMobileOtp, verify, abhaNumberAlreadyWith,
enterTenDigitMobileNumber) currently contain English values; replace each value
with the correct Hindi (Devanagari) translation matching the file’s existing
style (for example enterMobileNumberToBeLinkedWithAbha -> "ABHA से जोड़ने के लिए
फोन नंबर दर्ज करें", verify -> "सत्यापित करें") ensuring punctuation and
capitalization follow local conventions, and run a quick lint/validation of the
JSON to confirm no syntax changes were introduced.




Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Documentation
✏️ Tip: You can customize this high-level summary in your review settings.